﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using GauntletFramework.StateManagment;
using GauntletFramework.StateManagment.Menu;
using GauntletFramework.StateManagment.Menu.Menus;
using GauntletFramework.StateManagment.Transition;


namespace GauntletFramework.StateManagment
{
    public enum TransitionType
    {
        SlideLeft, SlideRight, FadeBlack
    }

    public class StateStack : DrawableGameComponent
    {
        public StateStack()
            : base((Game)StaticGame.Game)
        {
            States = new Stack<State>();
        }

        public float TransitionTime = 0.333f;
        public TransitionType TransitionType;

        public int Count { get { return States.Count; } }
        //stack
        protected Stack<State> States;
        private void push(State State)
        {
            if (!State.ContentLoaded) State.LoadContent();
            State.Awakened();
            States.Push(State);
        }
        private State pop()
        {
            return States.Pop();
        }


        public void PushState(State State)
        {
            TransitionState TS = null;
            if (State.StartTransition && States.Count >= 1)
            {
                State TransStart = States.Peek();
                State TransEnd = State;
                TS = CreateTransition();
                TS.AssignStates(TransStart, TransEnd);
            }
            push(State);
            if (TS != null)
                push(TS);
            
            StaticGame.BasicInput.PhoneInputState = PeekState().DefualtPhoneInputState;
            
            GameOrientation GO = PeekState().GameOrientation;
            
            if (GO == GameOrientation.Horizontal)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.PreferredBackBufferWidth = 800;
                graphics.PreferredBackBufferHeight = 480;
                graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
                graphics.ApplyChanges();
            }
            else if (GO == GameOrientation.Vertical)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.PreferredBackBufferWidth = 480;
                graphics.PreferredBackBufferHeight = 800;
                graphics.SupportedOrientations = DisplayOrientation.Portrait;
                graphics.ApplyChanges();
            }
            else if (GO == GameOrientation.Both)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.SupportedOrientations = DisplayOrientation.Default | DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight | DisplayOrientation.Portrait;
                graphics.ApplyChanges();
            }
        }

        public State PopState(int? PopCount = 1)
        {
            if (PopCount < 1)
                PopCount = 1;
            if (PopCount > States.Count)
                PopCount = States.Count;

            State Old = pop();
            for (int i = 1; i < PopCount; i++) pop();

            if (Old.EndTransition && States.Count >= 1)
            {
                State TransStart = Old;
                State TransEnd = States.Peek();
                TransitionState TS = CreateTransition();
                TS.AssignStates(TransStart, TransEnd);
                States.Push(TS);
            }

            if (States.Count <= 0) return Old;

            StaticGame.BasicInput.PhoneInputState = PeekState().DefualtPhoneInputState;

            GameOrientation GO = PeekState().GameOrientation;

            if (GO == GameOrientation.Horizontal)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.PreferredBackBufferWidth = 800;
                graphics.PreferredBackBufferHeight = 480;
                graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
                graphics.ApplyChanges();
            }
            else if (GO == GameOrientation.Vertical)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.PreferredBackBufferWidth = 480;
                graphics.PreferredBackBufferHeight = 800;
                graphics.SupportedOrientations = DisplayOrientation.Portrait;
                graphics.ApplyChanges();
            }
            else if (GO == GameOrientation.Both)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.SupportedOrientations = DisplayOrientation.Default | DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight | DisplayOrientation.Portrait;
                graphics.ApplyChanges();
            }

            if (States.Count > 0) States.Peek().Awakened();

            return Old;
        }

        public State PeekState()
        {
            return States.Peek();
        }

        public void ReplaceTopState(State State)
        {
            State Old = pop();
            push(State);

            if (Old.EndTransition || State.StartTransition)
            {
                State TransStart = Old;
                State TransEnd = State;
                TransitionState TS = CreateTransition();
                TS.AssignStates(TransStart, TransEnd);
                push(TS);
            }

            StaticGame.BasicInput.PhoneInputState = PeekState().DefualtPhoneInputState;

            GameOrientation GO = PeekState().GameOrientation;

            if (GO == GameOrientation.Horizontal)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.PreferredBackBufferWidth = 800;
                graphics.PreferredBackBufferHeight = 480;
                graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;
                graphics.ApplyChanges();
            }
            else if (GO == GameOrientation.Vertical)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.PreferredBackBufferWidth = 480;
                graphics.PreferredBackBufferHeight = 800;
                graphics.SupportedOrientations = DisplayOrientation.Portrait;
                graphics.ApplyChanges();
            }
            else if (GO == GameOrientation.Both)
            {
                GraphicsDeviceManager graphics = StaticGame.Game.graphics;
                graphics.SupportedOrientations = DisplayOrientation.Default | DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight | DisplayOrientation.Portrait;
                graphics.ApplyChanges();
            }
        }

        public void BackToMenu()
        {
            State Top = States.Peek();
            while (!(States.Peek() is MainMenu) && States.Count > 0)
            {
                pop();
            }
            State Bottom = States.Peek();

            TransitionState TS = null;
            if (Top.EndTransition)
            {
                TS = CreateTransition(); 
                TS.AssignStates(Top, Bottom);
            }
            if (TS != null)
                push(TS);
        }

        TransitionState CreateTransition()
        {
            switch(TransitionType)
            {
                case TransitionType.SlideLeft:
                    return new SlideLeftTransitionState(TransitionTime);
                case TransitionType.SlideRight:
                    return new SlideRightTransitionState(TransitionTime);
                case TransitionType.FadeBlack:
                    return new FadeBlackTransitionState(TransitionTime);
            }

            return new FadeBlackTransitionState(TransitionTime);
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            if (Count <= 0)
                return;

            State Current = States.Peek();
            
            Current.Update(gameTime);
            
            if (Current.Finished)
                PopState();
            
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            if (Count <= 0)
                return;

            State Current = States.Peek();

            Current.Draw(gameTime);
        }
    }
}
